#include <windows.h>
#include "CDXRenderer.h"
#include "CReleaseMacro.h"
#include <assert.h>
#include <d2d1helper.h>
#include <math.h>
#include <cmath>
#define MESHNAME_UNITRECT "UnitRect"
#define MESHNAME_BORDERRECT "BorderRect"
#define FXNAME_BASICRENDER "BasicRender"
using namespace D2D1;

bool CDXRenderer::FxElem::operator == (const CDXRenderer::FxElem& fx2)
{
	return (pEffect == fx2.pEffect) && (passIdx == fx2.passIdx) && (techIdx == fx2.techIdx); 
}

CDXRenderer::CDXRenderer(CDXDevice* pDevice) : CDXBase(pDevice)
{
	m_bD3DDrawing = FALSE;
	m_bD2DDrawing = FALSE;
	m_bD2DDrawingEndByD3D = FALSE;
	m_pFrameBuffer = NULL;
	m_pDepthBuffer = NULL;
	m_pRenderGeometry = NULL;
	m_pColorBrushLibrary = new CD2DColorBrushLibrary(pDevice);
	m_pEffectLibrary = new CDXEffectLibrary(pDevice);
	m_pMeshLibrary = new CDXMeshLibrary(pDevice);
	m_bDrawCmdQueue10Locked = FALSE;
	m_bDrawCmdQueue11Locked = FALSE;
	D3DXMatrixOrthoLH(&m_matProj, 1.0, 1.0, 1, 1000);
	D3DXMatrixLookAtLH(&m_matView, &D3DXVECTOR3(0,0,100), &D3DXVECTOR3(0,0,0), &D3DXVECTOR3(0,-1,0));
	m_FrameBufferFmt = DXGI_FORMAT_B8G8R8A8_UNORM;
	m_pClipRect = NULL;
	_Init();
}
CDXRenderer::~CDXRenderer()
{
	SAFE_RELEASE(m_pFrameBuffer);
	SAFE_RELEASE(m_pDepthBuffer);
	SAFE_RELEASE(m_pRenderGeometry);
	SAFE_RELEASE(m_Fx.pEffect);
	SAFE_DELETE(m_pColorBrushLibrary);
	SAFE_DELETE(m_pEffectLibrary);
	SAFE_DELETE(m_pMeshLibrary);
	SAFE_DELETE(m_pClipRect);
	for (UINT i =0; i < m_pFrameBufferStack.size(); i++)
	{
		SAFE_RELEASE(m_pFrameBufferStack[i]);
	}
	m_pFrameBufferStack.clear();
	for (UINT i =0; i < m_pDepthBufferStack.size(); i++)
	{
		SAFE_RELEASE(m_pDepthBufferStack[i]);
	}
	m_pDepthBufferStack.clear();
	for (UINT i =0; i < m_pDefaultDepthBuffer.size(); i++)
	{
		SAFE_RELEASE(m_pDefaultDepthBuffer[i]);
	}
	m_pDefaultDepthBuffer.clear();
	for (UINT i =0; i < m_pDepthStencilStateCache.size(); i++)
	{
		SAFE_RELEASE(m_pDepthStencilStateCache[i]);
	}
	m_pDepthStencilStateCache.clear();
	for (UINT i =0; i < m_FxStack.size(); i++)
	{
		SAFE_RELEASE(m_FxStack[i].pEffect);
	}
	m_FxStack.clear();
	for (UINT i =0; i < m_clipRectStack.size(); i++)
	{
		SAFE_DELETE(m_clipRectStack[i]);
	}
	m_clipRectStack.clear();
	
	UnLockAndClearDrawCmdResource10();
	UnLockAndClearDrawCmdResource11();
}
HRESULT CDXRenderer::_initColorBrushLibrary()
{
	return S_OK;
}
HRESULT CDXRenderer::_initEffectLibrary()
{
	if (m_pEffectLibrary == NULL)
	{
		m_pEffectLibrary = new CDXEffectLibrary(m_pDevice);
	}
	HRESULT hr = S_OK;
	hr = m_pEffectLibrary->LoadEffectFromFile(L"FX\\CDXBasicRender.fx", FXNAME_BASICRENDER);
	if (FAILED(hr))
		return hr;
	return S_OK;
}
HRESULT CDXRenderer::_updateBordMesh(const D2D1_RECT_F& rect, const float bordW[4], UINT texW, UINT texH)
{
	if (m_pMeshLibrary == NULL)
	{
		assert(0);
		return E_FAIL;
	}
	HRESULT hr = S_OK;
	CDXMesh* pBordMesh = NULL;
	hr = m_pMeshLibrary->GetMeshByName(MESHNAME_BORDERRECT, &pBordMesh);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	D3DXVECTOR3 vt[16] = {D3DXVECTOR3(rect.left, rect.top, 0), D3DXVECTOR3(rect.right, rect.top, 0), D3DXVECTOR3(rect.right, rect.bottom, 0), D3DXVECTOR3(rect.left, rect.bottom, 0), // Out 4 corner
		D3DXVECTOR3(rect.left+bordW[0], rect.top+bordW[1], 0), D3DXVECTOR3(rect.right-bordW[2], rect.top+bordW[1], 0), D3DXVECTOR3(rect.right-bordW[2], rect.bottom-bordW[3], 0), D3DXVECTOR3(rect.left+bordW[0], rect.bottom-bordW[3], 0), // inner 4 corner
        D3DXVECTOR3(rect.left+bordW[0], rect.top, 0), D3DXVECTOR3(rect.right-bordW[2], rect.top, 0),  // Top
		D3DXVECTOR3(rect.left+bordW[0], rect.bottom, 0), D3DXVECTOR3(rect.right-bordW[2], rect.bottom, 0),  // Bottom
		D3DXVECTOR3(rect.left, rect.top+bordW[1], 0), D3DXVECTOR3(rect.left, rect.bottom- bordW[3], 0),  // Left
		D3DXVECTOR3(rect.right, rect.top+bordW[1], 0), D3DXVECTOR3(rect.right, rect.bottom- bordW[3], 0)}; 
	
	
	float bordUV[4] = {bordW[0]/texW, bordW[1]/texH, bordW[2]/texW, bordW[3]/texH};

	D3DXVECTOR2 texcoordBuf[16] = {D3DXVECTOR2(0, 0), D3DXVECTOR2(1, 0), D3DXVECTOR2(1, 1), D3DXVECTOR2(0, 1), // Out 4 corner
		D3DXVECTOR2(0+bordUV[0], 0+bordUV[1]), D3DXVECTOR2(1-bordUV[2], 0+bordUV[1]), D3DXVECTOR2(1-bordUV[2], 1-bordUV[3]), D3DXVECTOR2(0+bordUV[0], 1-bordUV[3]), // inner 4 corner
		D3DXVECTOR2(0+bordUV[0], 0), D3DXVECTOR2(1-bordUV[2], 0),  // Top
		D3DXVECTOR2(0+bordUV[0], 1), D3DXVECTOR2(1-bordUV[2], 1),  // Bottom
		D3DXVECTOR2(0, 0+bordUV[1]), D3DXVECTOR2(0, 1- bordUV[3]),  // Left
		D3DXVECTOR2(1, 0+bordUV[1]), D3DXVECTOR2(1, 1- bordUV[3]) }; // RIGHT

	hr = pBordMesh->SetVertexPosition((float*)vt, 16);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	hr = pBordMesh->SetVertexTexcoord((float*)texcoordBuf, 0, 16);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}

	return hr;
}
HRESULT CDXRenderer::_initMeshLibrary()
{
	if (m_pMeshLibrary == NULL)
	{
		m_pMeshLibrary = new CDXMeshLibrary(m_pDevice);
	}
	HRESULT hr = S_OK;
	///////Unit Rectangle
	CDXMesh* pUnitRect = new CDXMesh(m_pDevice);
	D3DXVECTOR3 vertBuf[] = {D3DXVECTOR3(0.0, 0.0, 0), D3DXVECTOR3(1.0, 0.0, 0), D3DXVECTOR3(1.0, 1.0, 0), D3DXVECTOR3(0.0, 1.0, 0)};
	                        
	D3DXVECTOR3 normalBuf[] = {D3DXVECTOR3(0,0,-1), D3DXVECTOR3(0, 0, -1), D3DXVECTOR3(0, 0, -1), D3DXVECTOR3(0, 0, -1)};
	D3DXVECTOR2 texcoordBuf[] = {D3DXVECTOR2(0,0), D3DXVECTOR2(1, 0), D3DXVECTOR2(1, 1), D3DXVECTOR2(0, 1)};
	UINT idxBuf[] = {0,2,1, 0,3,2};
	hr = pUnitRect->CreateMesh(4, vertBuf, normalBuf, texcoordBuf, idxBuf, 6);
	m_pMeshLibrary->SetMesh(pUnitRect, MESHNAME_UNITRECT);
	SAFE_RELEASE(pUnitRect);
	///////Border Rectangle
	CDXMesh* pBorderRect = new CDXMesh(m_pDevice);
	D3DXVECTOR3 bordernormalBuf[16] = {D3DXVECTOR3(0,0,-1)};
	hr = pBorderRect->CreateVertexBuffer(VB_POSITION, 16, NULL);
	hr = pBorderRect->CreateVertexBuffer(VB_TEXCOORD0, 16, NULL);
	hr = pBorderRect->CreateVertexBuffer(VB_NORMAL, 16, (void*)bordernormalBuf);
	UINT  borderidxBuf[] = {0, 8, 4,    0, 4, 12,     8, 9, 5,       8, 5, 4,         9, 1, 14,   9, 14, 5,     
	                 12, 4, 7,   12, 7, 13,    4, 5, 6,       4, 6, 7,         5, 14, 15,  5, 15, 6, 
	                 13, 7, 10,  13, 10, 3,    7, 6, 11,      7, 11, 10,       6, 15, 2,   6, 2, 11};
	hr = pBorderRect->CreateIndexBuffer(ARRAYSIZE( borderidxBuf), (void*)borderidxBuf);
	m_pMeshLibrary->SetMesh( pBorderRect, MESHNAME_BORDERRECT);

	SAFE_RELEASE(pBorderRect);

	return hr;
}
HRESULT CDXRenderer::_Init()
{
	HRESULT hr = S_OK;
	hr = _InitDepthState();
	if (FAILED(hr))
		return hr;
    hr = _initEffectLibrary();
	if (FAILED(hr))
		return hr;
	hr = _initColorBrushLibrary();
	if (FAILED(hr))
		return hr;
	hr = _initMeshLibrary();
	if (FAILED(hr))
		return hr;
	
	return hr;;
}
HRESULT CDXRenderer::_InitDepthState()
{
	HRESULT hr = S_OK;
	D3D11_DEPTH_STENCIL_DESC dsDesc;
	// Depth test parameters
	dsDesc.DepthEnable = true;
	dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
	dsDesc.DepthFunc = D3D11_COMPARISON_LESS;

	// Stencil test parameters
	dsDesc.StencilEnable = true;
	dsDesc.StencilReadMask = 0xFF;
	dsDesc.StencilWriteMask = 0xFF;

	// Stencil operations if pixel is front-facing
	dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
	dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

	// Stencil operations if pixel is back-facing
	dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
	dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
	dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
	dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

	hr = SetDepthStencilState(&dsDesc);

	return hr;
}
HRESULT CDXRenderer::_GetDefaultDepthBuffer(UINT width, UINT height, CDXTexture2D** ppDepthBuffer)
{
	D3D11_TEXTURE2D_DESC desc;
	for (UINT i =0; i < m_pDefaultDepthBuffer.size(); i++)
	{
		m_pDefaultDepthBuffer[i]->GetDesc(&desc);
		if (desc.Width == width && desc.Height == height)
		{
			*ppDepthBuffer = m_pDefaultDepthBuffer[i];
			return S_OK;
		}
	}
	D3D11_TEXTURE2D_DESC descDepth;
	descDepth.Width = width;
	descDepth.Height = height;
	descDepth.MipLevels = 1;
	descDepth.ArraySize = 1;
	descDepth.Format = DXGI_FORMAT_D32_FLOAT;
	descDepth.SampleDesc.Count = 1;
	descDepth.SampleDesc.Quality = 0;
	descDepth.Usage = D3D11_USAGE_DEFAULT;
	descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
	descDepth.CPUAccessFlags = 0;
	descDepth.MiscFlags = 0;
	CDXTexture2D* pDepthTexture = new CDXTexture2D(m_pDevice);
	pDepthTexture->Create(&descDepth, NULL);
	m_pDefaultDepthBuffer.push_back(pDepthTexture);
	*ppDepthBuffer = pDepthTexture;
	return S_OK;
}
HRESULT CDXRenderer::_CreateDepthStencilState(D3D11_DEPTH_STENCIL_DESC* pDesc, ID3D11DepthStencilState** ppState)
{
	if (m_pDevice == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	
	D3D11_DEPTH_STENCIL_DESC checkDesc;
	for (UINT i =0; i < m_pDepthStencilStateCache.size(); i++)
	{
		m_pDepthStencilStateCache[i]->GetDesc(&checkDesc);
		if (memcmp(&checkDesc, pDesc, sizeof(D3D11_DEPTH_STENCIL_DESC)) == 0)
		{
			SAFE_RELEASE(*ppState);
			*ppState = m_pDepthStencilStateCache[i];
			return S_OK;
		}
	}

	ID3D11DepthStencilState* pSState = NULL;
	ID3D11Device* pDX11Device = m_pDevice->GetD3D11Device();
	hr = pDX11Device->CreateDepthStencilState(pDesc, &pSState);
	if (FAILED(hr))
		return hr;
	m_pDepthStencilStateCache.push_back(pSState);

	*ppState = pSState;
	return S_OK;
}
HRESULT CDXRenderer::SetDepthStencilState(D3D11_DEPTH_STENCIL_DESC* pStateDesc)
{
	if (m_pDevice == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DepthStencilState * pDSState = NULL;
	hr = _CreateDepthStencilState(pStateDesc, &pDSState);
	if (FAILED(hr))
		return hr;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	pContext->OMSetDepthStencilState(pDSState, 1);
	return S_OK;
}
HRESULT CDXRenderer::GetDepthStencilState(D3D11_DEPTH_STENCIL_DESC* pStateDesc) 
{
	if (m_pDevice == NULL)
		return E_FAIL;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	UINT refCount = 0;
	ID3D11DepthStencilState* pState = NULL;
	pContext->OMGetDepthStencilState(&pState, &refCount);
	pState->GetDesc(pStateDesc);
	SAFE_RELEASE(pState);
	return S_OK;
}
BOOL CDXRenderer::_IsValidFrameBuffer(CDXTexture2D* pFrameBuf)
{
	if (pFrameBuf == NULL)
		return FALSE;
	if (!IsSameDevice(pFrameBuf))
		return FALSE;
	HRESULT hr = S_OK;
	ID3D11RenderTargetView* pRTView = NULL;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = pFrameBuf->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
	{
		assert(0);
		return FALSE;
	}
	hr = pFrameBuf->GetRenderTargetView(NULL, &pRTView);
	if (FAILED(hr))
		return FALSE;
	
	return TRUE;
}
BOOL CDXRenderer::_IsValidDepthBuffer(CDXTexture2D* pDepthBuf)
{
	if (pDepthBuf == NULL)
		return FALSE;
	if (!IsSameDevice(pDepthBuf))
		return FALSE;
	HRESULT hr = S_OK;
	ID3D11DepthStencilView* pDSV = NULL;
	
	hr = pDepthBuf->GetDepthStencilView(NULL, &pDSV);
	if (FAILED(hr))
		return FALSE;
	
	return TRUE;
}
HRESULT CDXRenderer::_CalcStretchTypeSrcRect(StretchType sType, const D2D1_RECT_F& inDstRect, float srcW, float srcH, D2D1_RECT_F& outDstRect, D2D1_RECT_F& outSrcRect)
{
	if (srcH <= 0 || srcW <= 0)
	{
		assert(0);
		return E_FAIL;
	}
	float dstW = inDstRect.right - inDstRect.left;
	float dstH = inDstRect.bottom - inDstRect.top;
	float dstRatio = dstW / dstH;
	float srcRatio = srcW / srcH; 
	outSrcRect = D2D1::RectF(0, 0, srcW, srcH);
	outDstRect = inDstRect;
	if (sType == Fill)
	{
		//do nothing
	}
	else if(sType == Uniform)
	{
		if (srcRatio > dstRatio)
		{
			float centerY = (float)((inDstRect.top + inDstRect.bottom)*0.5);
			float halfH = (float)(dstW*(1.0/srcRatio)*0.5);
			outDstRect.left = inDstRect.left;
			outDstRect.right = inDstRect.right;
			outDstRect.top = centerY - halfH;
			outDstRect.bottom = centerY + halfH;
		}
		else 
		{
			float centerX = (float)((inDstRect.left + inDstRect.right)*0.5);
			float halfW =(float)(dstH*srcRatio*0.5);
			outDstRect.left = centerX - halfW;
			outDstRect.right = centerX + halfW;
			outDstRect.top = inDstRect.top;
			outDstRect.bottom = inDstRect.bottom;
		}
	}
	else if(sType == UniformFill)
	{
		if (srcRatio > dstRatio)
		{
			float centerX = (float)(srcW*0.5); 
			float halfW = (float)(srcH*dstRatio*0.5);
			outSrcRect.top = 0;
			outSrcRect.bottom = srcH;
			outSrcRect.left = centerX - halfW;
			outSrcRect.right = centerX + halfW;
		}
		else 
		{
			float centerY = (float)(srcH*0.5); 
			float halfH = (float)(srcW*(1.0/dstRatio)*0.5);
			outSrcRect.left = 0;
			outSrcRect.right = srcW;
			outSrcRect.top = centerY - halfH;
			outSrcRect.bottom = centerY + halfH;
		}
	}
	else if (sType == NoStretch )
	{
		
		float dstCenterX = (float)(inDstRect.left + dstW*0.5);
		float dstCenterY = (float)(inDstRect.top + dstH*0.5);
		float srcCenterX = (float)(srcW*0.5);
		float srcCenterY = (float)(srcH*0.5);
		if (dstW > srcW)
		{
			outDstRect.left = dstCenterX - srcW*0.5;
			outDstRect.right = dstCenterX + srcW*0.5;
		}
		else
		{
			outSrcRect.left = srcCenterX - dstW*0.5;
			outSrcRect.right = srcCenterX + dstW*0.5;
		}
		if (dstH > srcH)
		{
			outDstRect.top = dstCenterY - srcH*0.5;
			outDstRect.bottom = dstCenterY + srcH*0.5;
		}
		else
		{
			outSrcRect.top = srcCenterY - dstH*0.5;
			outSrcRect.bottom = srcCenterY + dstH*0.5;
		}
	}
	else 
	{
		assert(0);
		return E_FAIL;
	}
	return S_OK;
}
HRESULT CDXRenderer::UpdateCamViewByViewport()
{
	if (m_pDevice == NULL)
	{
		assert(0);
		return E_FAIL;
	}
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pDeviceContext = m_pDevice->GetD3D11DeviceContext();
	UINT nViewport = 1;
	D3D11_VIEWPORT viewport;
	pDeviceContext->RSGetViewports(&nViewport, &viewport);
	D3DXVECTOR2 center(0, 0);
	center.x = (float)(viewport.TopLeftX + viewport.Width*0.5);
	center.y = (float)(viewport.TopLeftY + viewport.Height*0.5);
	D3DXMatrixOrthoLH(&m_matProj, viewport.Width, viewport.Height, 1, 1000);
	D3DXMatrixLookAtLH(&m_matView, &D3DXVECTOR3(center.x,center.y, 100), &D3DXVECTOR3(center.x,center.y, 0), &D3DXVECTOR3(0,-1,0));

	return S_OK;
	
}
HRESULT CDXRenderer::UpdateViewportByFrameBuf()
{
	if (m_pFrameBuffer == NULL)
	{
		assert(0);
		return E_FAIL;
	}
	HRESULT hr = S_OK;
	UINT frameW = 0, frameH = 0;
	m_pFrameBuffer->GetFrameSize(&frameW, &frameH);
	D3D11_VIEWPORT viewport;
	viewport.Width = (float)frameW;
	viewport.Height = (float)frameH;
	viewport.TopLeftX = 0;
	viewport.TopLeftY = 0;
	viewport.MaxDepth = 1.0;
	viewport.MinDepth = 0.0;

	hr = SetViewPort(&viewport, FALSE);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	return hr;
}


HRESULT CDXRenderer::BindFrameBuffersToDevice()
{
	if (m_pDevice == NULL || m_pFrameBuffer == NULL || m_pDepthBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pDeviceContext = m_pDevice->GetD3D11DeviceContext();
	ID3D11RenderTargetView* pRTView = NULL;
	ID3D11DepthStencilView* pDSView = NULL;
	hr = m_pFrameBuffer->GetRenderTargetView(NULL, &pRTView);
	if (FAILED(hr))
		return hr;
	hr = m_pDepthBuffer->GetDepthStencilView(NULL, &pDSView);
	if (FAILED(hr))
		return hr;
	m_pFrameBuffer->KeyMutex11Acquire();
	m_pDepthBuffer->KeyMutex11Acquire();
	pDeviceContext->OMSetRenderTargets(1, &pRTView, pDSView);
	m_pDepthBuffer->KeyMutex11Release();
	m_pFrameBuffer->KeyMutex11Release();
	return S_OK;
}
HRESULT CDXRenderer::UnbindFrameBufferFromDevice()
{
	if (m_pDevice == NULL)
		return E_FAIL;
	ID3D11DeviceContext* pDeviceContext = m_pDevice->GetD3D11DeviceContext();
	pDeviceContext->OMSetRenderTargets(0, NULL, NULL);
	return S_OK;
}
HRESULT CDXRenderer::BindInputLayout()
{
	if (m_pDevice == NULL || m_pRenderGeometry == NULL || m_Fx.pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	ID3DX11Effect* pEffect = m_Fx.pEffect->GetEffect();
	ID3D11InputLayout* pLayout = NULL;
	hr = m_pRenderGeometry->GetInputLayout(pEffect, m_Fx.techIdx, m_Fx.passIdx, &pLayout);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	
	pContext->IASetInputLayout(pLayout);
	return hr;
}
HRESULT CDXRenderer::BindRenderGeometryToDevice()
{
	if (m_pDevice == NULL || m_pRenderGeometry == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	ID3D11Buffer* pIdxBuf = NULL;
	hr = m_pRenderGeometry->GetIndexBuffer(&pIdxBuf);
	if (FAILED(hr))
		return hr;
	UINT nVertexBuf = 1;
	m_pRenderGeometry->GetNumVertexBuffers(&nVertexBuf);
	ID3D11Buffer** pVertBufs = new ID3D11Buffer*[nVertexBuf];
	UINT* vertBufStrides = new UINT[nVertexBuf];
	UINT* vertBufOffset = new UINT[nVertexBuf];

	hr = m_pRenderGeometry->GetVertexBuffers(pVertBufs, vertBufStrides, vertBufOffset);
	if (FAILED(hr))
	{
		SAFE_DELETE_ARRAY(pVertBufs);
		SAFE_DELETE_ARRAY(vertBufOffset);
		SAFE_DELETE_ARRAY(vertBufStrides);
		return hr;
	}
	
	D3D11_PRIMITIVE_TOPOLOGY topology = m_pRenderGeometry->GetPrimitiveTopology();
	pContext->IASetPrimitiveTopology(topology);
	pContext->IASetIndexBuffer(pIdxBuf, DXGI_FORMAT_R32_UINT, 0);
	pContext->IASetVertexBuffers(0, nVertexBuf, pVertBufs, vertBufStrides, vertBufOffset);

	SAFE_DELETE_ARRAY(pVertBufs);
	SAFE_DELETE_ARRAY(vertBufOffset);
	SAFE_DELETE_ARRAY(vertBufStrides);
	return hr;
}

HRESULT CDXRenderer::BindEffectToDevice()
{
	if (m_pDevice == NULL || m_Fx.pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	ID3DX11Effect* pEffect = m_Fx.pEffect->GetEffect();
	ID3DX11EffectTechnique* pTech = pEffect->GetTechniqueByIndex(m_Fx.techIdx);
	if (pTech == NULL)
		return E_FAIL;

	ID3DX11EffectPass* pPass = pTech->GetPassByIndex(m_Fx.passIdx);
	m_Fx.pEffect->LockKeyMutexResources();
	pPass->Apply(0, pContext);
	
	return hr;
}
HRESULT CDXRenderer::UnBindEffectFromDevice()
{
	if (m_pDevice == NULL || m_Fx.pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();

	pContext->VSSetShader(NULL, NULL, 0);
	pContext->PSSetShader(NULL, NULL, 0);
	pContext->CSSetShader(NULL, NULL, 0);
	pContext->HSSetShader(NULL, NULL, 0);
	pContext->GSSetShader(NULL, NULL, 0);
	

	ID3D11ShaderResourceView *const pSRVNULL[D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {NULL};
	ID3D11UnorderedAccessView* const pUAVNULL[D3D11_PS_CS_UAV_REGISTER_COUNT] = {NULL};
	ID3D11Buffer* const pCSCBNULL[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {NULL};
	UINT pUAVInitCount[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0};
	pContext->CSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, pSRVNULL);
	pContext->VSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, pSRVNULL);
	pContext->PSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, pSRVNULL);
	pContext->GSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, pSRVNULL); 
	pContext->HSSetShaderResources(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, pSRVNULL); 
	pContext->CSSetUnorderedAccessViews(0, D3D11_PS_CS_UAV_REGISTER_COUNT, pUAVNULL, pUAVInitCount);

	m_Fx.pEffect->UnLockKeyMutexResources();
	return S_OK;
}

HRESULT CDXRenderer::BindMatrixToStdVs()
{
	if (m_pDevice == NULL || m_Fx.pEffect == NULL)
		return E_FAIL;
	D3DXMATRIX worldMat = GetTransform();
	D3DXMATRIX viewMat = GetViewMatrix();
	D3DXMATRIX projMat = GetProjectMatrix();
	D3DXMATRIX worldViewProj = worldMat*viewMat*projMat;
	m_Fx.pEffect->SetMatrixVariableBySemantic("WORLD_MATRIX", (float*)worldMat, false);
	m_Fx.pEffect->SetMatrixVariableBySemantic("VIEW_MATRIX", (float*)viewMat, false);
	m_Fx.pEffect->SetMatrixVariableBySemantic("PROJ_MATRIX", (float*)projMat, false);
	m_Fx.pEffect->SetMatrixVariableBySemantic("WORLDVIEWPROJ", (float*)worldViewProj, false);

	return S_OK;
}


HRESULT CDXRenderer::BindD2DTransform()
{
	if (m_pFrameBuffer == NULL)
	{
		assert(0);
		return E_FAIL;
	}
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	Matrix3x2F matI;
	matI.Identity();
	Matrix3x2F matTran = GetTransform2D();
	pD2DRT->SetTransform(matTran);
	return S_OK;
}
HRESULT CDXRenderer::UnbindD2DTransform()
{
	if (m_pFrameBuffer == NULL)
	{
		assert(0);
		return E_FAIL;
	}
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	Matrix3x2F matI;
	matI.Identity();
	pD2DRT->SetTransform(matI);
	return S_OK;
}

HRESULT CDXRenderer::BindD2DClipRect()
{
	if (m_pClipRect == NULL)
		return S_FALSE;
	if (m_pFrameBuffer == NULL )
	{
		assert(0);
		return E_FAIL;
	}
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	for (int c =1; c < m_clipRectStack.size(); c++) // start from index 1, because the 0 is NULL
	{
		D3DXVECTOR3 localPts[4];
		InvTransform3DPoints(localPts, m_clipRectStack[c]->clipRect, 4);
		float l = localPts[0].x;
		float r = localPts[0].x;
		float t = localPts[0].y;
		float b = localPts[0].y;
		for(UINT i = 1; i < 4; i++)
		{
			l = min(l, localPts[i].x);
			r = max(r, localPts[i].x);
			t = min(t, localPts[i].y);
			b = max(b, localPts[i].y);
		}

		D2D_RECT_F cRect = {l, t, r, b };
		pD2DRT->PushAxisAlignedClip(cRect, m_clipRectStack[c]->antialiasMode);
	}

	D3DXVECTOR3 localPts[4];
	InvTransform3DPoints(localPts, m_pClipRect->clipRect, 4);
	float l = localPts[0].x;
	float r = localPts[0].x;
	float t = localPts[0].y;
	float b = localPts[0].y;
	for(UINT i = 1; i < 4; i++)
	{
		l = min(l, localPts[i].x);
		r = max(r, localPts[i].x);
		t = min(t, localPts[i].y);
		b = max(b, localPts[i].y);
	}

	D2D_RECT_F cRect = {l, t, r, b };
	pD2DRT->PushAxisAlignedClip(cRect, m_pClipRect->antialiasMode);

	return S_OK;
}
HRESULT CDXRenderer::UnbindD2DClipRect()
{
	if (m_pClipRect == NULL)
		return S_FALSE;
	if (m_pFrameBuffer == NULL )
	{
		assert(0);
		return E_FAIL;
	}
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	for (int c =1; c < m_clipRectStack.size(); c++)
	{
		pD2DRT->PopAxisAlignedClip();
	}
	pD2DRT->PopAxisAlignedClip();
	return S_OK;

}
HRESULT CDXRenderer::BindResourcesToDevice()
{
	HRESULT hr = S_OK;
	hr = BindFrameBuffersToDevice();
	if (FAILED(hr))
		return hr;
	hr = BindRenderGeometryToDevice();
	if (FAILED(hr))
		return hr;
	hr = BindEffectToDevice();
	if (FAILED(hr))
		return hr;
	hr = BindInputLayout();
	return hr;
}
HRESULT CDXRenderer::SetFrameBuffer(CDXTexture2D* pFrameBuffer, BOOL bUpdateViewport, BOOL bUpdateCamView)
{
	if (!_IsValidFrameBuffer(pFrameBuffer))
	{
		assert(0);
		return E_FAIL;
	}
	if (m_pFrameBuffer == pFrameBuffer)
		return S_FALSE;

	HRESULT hr = S_OK;
	D3D11_TEXTURE2D_DESC desc;
	pFrameBuffer->GetDesc(&desc);
	CDXTexture2D* pDepthBuf = NULL;
	hr = this->_GetDefaultDepthBuffer(desc.Width, desc.Height, &pDepthBuf);
	if (FAILED(hr))
		return E_FAIL;
	SAFE_RELEASE(m_pFrameBuffer);
	SAFE_RELEASE(m_pDepthBuffer);
	m_pFrameBuffer = pFrameBuffer;
	m_pDepthBuffer = pDepthBuf;
	SAFE_ADDREF(m_pFrameBuffer);
	SAFE_ADDREF(m_pDepthBuffer);
	if (bUpdateViewport)
	{
		hr = UpdateViewportByFrameBuf();
		if (bUpdateCamView)
		{
			hr = UpdateCamViewByViewport();
		}
	}
	return hr;
}
HRESULT CDXRenderer::SetFrameBuffer(CDXTexture2D* pFrameBuffer, CDXTexture2D* pDepthBuffer, BOOL bUpdateViewport, BOOL bUpdateCamView)
{
	if (!_IsValidFrameBuffer(pFrameBuffer))
		return E_FAIL;
	if (!_IsValidDepthBuffer(pDepthBuffer))
		return E_FAIL;
	if (pFrameBuffer == m_pFrameBuffer && pDepthBuffer == m_pDepthBuffer)
		return S_FALSE;
	HRESULT hr = S_OK;
	D3D11_TEXTURE2D_DESC desc;
	pFrameBuffer->GetDesc(&desc);
	D3D11_TEXTURE2D_DESC depthDesc;
	pDepthBuffer->GetDesc(&depthDesc);
	if (depthDesc.Width != desc.Width || depthDesc.Height != desc.Height)
		return E_FAIL;

	CDXTexture2D* pBackupFrameBuf = m_pFrameBuffer;
	CDXTexture2D* pBackupDepthBuf = m_pDepthBuffer;
	m_pFrameBuffer = pFrameBuffer;
	m_pDepthBuffer = pDepthBuffer;
	SAFE_ADDREF(m_pFrameBuffer);
	SAFE_ADDREF(m_pDepthBuffer);
	SAFE_RELEASE(pBackupFrameBuf);
	SAFE_RELEASE(pBackupDepthBuf);
	hr = BindFrameBuffersToDevice();
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	if (bUpdateViewport)
	{
		hr = UpdateViewportByFrameBuf();
		if (bUpdateCamView)
		{
			hr = UpdateCamViewByViewport();
		}
	}
	return S_OK;
}
HRESULT CDXRenderer::GetFrameBuffer(CDXTexture2D** ppFrameBuffer,CDXTexture2D** ppDepthBuffer)
{
	*ppFrameBuffer = m_pFrameBuffer;
	*ppDepthBuffer = m_pDepthBuffer;
	return S_OK;
}

HRESULT CDXRenderer::PushFrameBuffer(CDXTexture2D* pFrameBuffer, BOOL bUpdateViewport, BOOL bUpdateCamView)
{
	HRESULT hr = S_OK;
	CDXTexture2D* pBackupFrameBuf = m_pFrameBuffer;
	CDXTexture2D* pBackupDepthBuf = m_pDepthBuffer;
	SAFE_ADDREF(pBackupFrameBuf);
	SAFE_ADDREF(pBackupDepthBuf);
	hr = SetFrameBuffer(pFrameBuffer, bUpdateViewport, bUpdateCamView);
	if (FAILED(hr))
		return hr;
	m_pFrameBufferStack.push_back(pBackupFrameBuf);
	m_pFrameBufferStack.push_back(pBackupDepthBuf);
	
	return S_OK;
}
HRESULT CDXRenderer::PushFrameBuffer(CDXTexture2D* pFrameBuffer, CDXTexture2D* pDepthBuffer, BOOL bUpdateViewport, BOOL bUpdateCamView)
{
	HRESULT hr = S_OK;
	CDXTexture2D* pBackupFrameBuf = m_pFrameBuffer;
	CDXTexture2D* pBackupDepthBuf = m_pDepthBuffer;
	SAFE_ADDREF(pBackupFrameBuf);
	SAFE_ADDREF(pBackupDepthBuf);
	hr = SetFrameBuffer(pFrameBuffer, pDepthBuffer, bUpdateViewport, bUpdateCamView );
	if (FAILED(hr))
		return hr;
	m_pFrameBufferStack.push_back(pBackupFrameBuf);
	m_pFrameBufferStack.push_back(pBackupDepthBuf);

	return S_OK;
}
HRESULT CDXRenderer::PopFrameBuffer(BOOL bUpdateViewport, BOOL bUpdateCamView)
{
	if (m_pFrameBufferStack.size() == 0 || m_pDepthBufferStack.size() == 0)
		return E_FAIL;
	CDXTexture2D* pFrameBuf = m_pFrameBufferStack.back();
	m_pFrameBufferStack.pop_back();
	CDXTexture2D* pDepthBuf = m_pDepthBufferStack.back();
	m_pDepthBufferStack.pop_back();

	HRESULT hr = S_OK;
	hr = SetFrameBuffer(pFrameBuf, pDepthBuf, bUpdateViewport, bUpdateCamView);
	SAFE_RELEASE(pFrameBuf);
	SAFE_RELEASE(pDepthBuf);
	hr = BindFrameBuffersToDevice();
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	
	return hr;
}
HRESULT CDXRenderer::SetFrameBufferFormat(DXGI_FORMAT fmt)
{
	m_FrameBufferFmt = fmt;
	return S_OK;
}
DXGI_FORMAT CDXRenderer::GetFrameBufferFormat()
{
	return m_FrameBufferFmt;
}
HRESULT CDXRenderer::SetEffect(ID3DX11Effect* pDXEffect, UINT techidx, UINT passIdx)
{
	if (pDXEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	CDXEffect* pEffect = new CDXEffect(m_pDevice);
	pEffect->SetEffect(pDXEffect);
	FxElem elem(pEffect, techidx, passIdx);
	SAFE_RELEASE(m_Fx.pEffect);
	m_Fx = elem;
	/*hr = BindEffectToDevice();
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}*/
	if (m_pRenderGeometry != NULL)
	{
		hr = BindInputLayout();
	}
	return hr;
}
HRESULT CDXRenderer::SetEffect(CDXEffect* pEffect, UINT techidx, UINT passIdx)
{
	if (pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	FxElem elem(pEffect, techidx, passIdx);
	if (elem == m_Fx)
	{
		return S_FALSE;
	}
	SAFE_ADDREF(pEffect);
	
	SAFE_RELEASE(m_Fx.pEffect);
	m_Fx = elem;
	/*hr = BindEffectToDevice();
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}*/
	if (m_pRenderGeometry != NULL)
	{
		hr = BindInputLayout();
	}
	return hr;
}
HRESULT CDXRenderer::GetEffect(ID3DX11Effect** pOutEffect)
{
	if (m_Fx.pEffect == NULL)
		return E_FAIL;
	*pOutEffect = m_Fx.pEffect->GetEffect();
	return S_OK;
}
HRESULT CDXRenderer::PushEffect()
{
	SAFE_ADDREF(m_Fx.pEffect);
	m_FxStack.push_back(m_Fx);
	return S_OK;
}
HRESULT CDXRenderer::PopEffect()
{
	if (m_FxStack.empty())
		return E_FAIL;
	HRESULT hr = S_OK;
	SAFE_RELEASE(m_Fx.pEffect);
	FxElem pFX = m_FxStack.back();
	m_FxStack.pop_back();
	if (pFX == m_Fx)
	{
		SAFE_RELEASE(pFX.pEffect);
		return S_FALSE;
	}
	SetEffect(pFX.pEffect, pFX.techIdx, pFX.passIdx);
	SAFE_RELEASE(pFX.pEffect);
	return hr;
}

HRESULT CDXRenderer::SetViewPort(const D3D11_VIEWPORT* viewport, BOOL bUpdateCamView)
{
	if (m_pDevice == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	pContext->RSSetViewports(1, viewport);
	if (bUpdateCamView)
	{
		hr = UpdateCamViewByViewport();
		if (FAILED(hr))
		{
			assert(0);
			return hr;
		}
	}
	return hr;
}
HRESULT CDXRenderer::GetViewPort(D3D11_VIEWPORT* viewport)
{
	if (m_pDevice == NULL || viewport == NULL)
	{
		assert(0);
		return E_FAIL;
	}
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	UINT nViewport = 1;
	pContext->RSGetViewports(&nViewport, viewport);
	return S_OK;
}

HRESULT CDXRenderer::SetRenderGeometry(CDXGeometry* pGeometry)
{
	if (m_pRenderGeometry == pGeometry)
		return S_FALSE;
	HRESULT hr = S_OK;
	SAFE_RELEASE(m_pRenderGeometry);
	m_pRenderGeometry = pGeometry;
	SAFE_ADDREF(pGeometry);
	hr = BindRenderGeometryToDevice();
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	if (m_Fx.pEffect != NULL)
	{
		hr = BindInputLayout();
	}
	return hr;
}
HRESULT CDXRenderer::PushRenderGeometry()
{
	m_pRenderGeometryStack.push_back(m_pRenderGeometry);
	SAFE_ADDREF(m_pRenderGeometry);

	return S_OK;
}
HRESULT CDXRenderer::PopRenderGeometry()
{
	if (m_pRenderGeometryStack.empty())
		return E_FAIL;
	HRESULT hr = S_OK;
	
	CDXGeometry* pGeometry = m_pRenderGeometryStack.back();
	m_pRenderGeometryStack.pop_back();
	if (pGeometry == m_pRenderGeometry)
	{
		SAFE_RELEASE(pGeometry);
		return S_FALSE;
	}
	if (pGeometry != NULL)
	{
		hr = SetRenderGeometry(pGeometry);
		SAFE_RELEASE(pGeometry);
	}
	else
	{
		SAFE_RELEASE(m_pRenderGeometry);
	}
	
	return hr;
}

HRESULT CDXRenderer::SetViewMatrix(const D3DXMATRIX* matView)
{
	m_matView = *matView;
	return S_OK;
}
D3DXMATRIX CDXRenderer::GetViewMatrix()
{
	return m_matView;
}
HRESULT CDXRenderer::SetProjectMatrix(const D3DXMATRIX* matProj)
{
	m_matProj = *matProj;
	return S_OK;
}
D3DXMATRIX CDXRenderer::GetProjectMatrix()
{
	return m_matProj;
}

HRESULT CDXRenderer::DrawD3D(BOOL bStdVS)
{
	if (m_pDevice == NULL || m_pRenderGeometry == NULL || m_Fx.pEffect == NULL)
		return E_FAIL;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	UINT nIdxCount = 0; 
	HRESULT hr = S_OK;
	if (bStdVS)
	{
		hr = BindMatrixToStdVs();
		if (FAILED(hr))
			return hr;
	}
	
	hr = m_pRenderGeometry->GetIndexCount(nIdxCount);
	if (FAILED(hr))
		return hr;
	m_pFrameBuffer->KeyMutex11Acquire();
	m_pDepthBuffer->KeyMutex11Acquire();
	hr = m_Fx.pEffect->LockKeyMutexResources();
	BindFrameBuffersToDevice();
	BindEffectToDevice();
	pContext->DrawIndexed(nIdxCount, 0, 0);
	UnBindEffectFromDevice();
	UnbindFrameBufferFromDevice();
	hr = m_Fx.pEffect->UnLockKeyMutexResources();
	m_pDepthBuffer->KeyMutex11Release();
	m_pFrameBuffer->KeyMutex11Release();
	return S_OK;
}

HRESULT CDXRenderer::DrawColorRectangleD3D(D2D1_RECT_F rect, FLOAT color[4])

{
	if (m_pDevice == NULL || m_pMeshLibrary == NULL || m_pEffectLibrary == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	CDXMesh* pUnitRect = NULL;
	hr = m_pMeshLibrary->GetMeshByName(MESHNAME_UNITRECT, &pUnitRect);
	if (FAILED(hr))
		return hr;
	CDXEffect* pEffect = NULL;
	hr = m_pEffectLibrary->GetEffectByName(FXNAME_BASICRENDER, &pEffect);
	if (FAILED(hr))
		return hr;
	float rectW = rect.right - rect.left;
	float rectH = rect.bottom - rect.top;
	if (rectW <=0 || rectH <= 0)
	{
		assert(0);
		return E_FAIL;
	}

	UINT stretchType = 0;
	BOOL bDrawTexture = FALSE;	
	UINT sampleType = 1; 
	bool bFlipY = false;
	bool bFlipX = false;
	float rtRatio = rectW / rectH;

	hr = pEffect->SetVariableByName("g_rtRatio", (void*)&rtRatio, 0, sizeof(rtRatio));
	hr = pEffect->SetVariableByName("g_bDrawTexture", (void*)&bDrawTexture, 0, sizeof(bDrawTexture));
	hr = pEffect->SetVariableByName("g_StretchType", (void*)&stretchType, 0, sizeof(stretchType) );
	hr = pEffect->SetVariableByName("g_color", color, 0, sizeof(FLOAT)*4);
	hr = pEffect->SetVariableByName("g_sampleType", (void*)&sampleType, 0, sizeof(sampleType));
	hr = pEffect->SetVariableByName("g_bFlipX", (void*)&bFlipX, 0, sizeof(bFlipX));
	hr = pEffect->SetVariableByName("g_bFlipY", (void*)&bFlipY, 0, sizeof(bFlipY));
	
	PushEffect();
	PushRenderGeometry();
	
	SetRenderGeometry(pUnitRect);
	SetEffect(pEffect, 0, 0);

	PushMatrix();
	TranslateLocal(rect.left, rect.top, 0.0);
	ScaleLocal(rectW, rectH, 1.0);
	DrawD3D(TRUE);
	PopMatrix();

	PopRenderGeometry();
	PopEffect();
	return S_OK;
}
HRESULT CDXRenderer::DrawTexturedRectangleD3D(D2D1_RECT_F rect, CDXTexture2D* pTexture, FLOAT color[4], StretchType sType)
{
	if (m_pDevice == NULL ||  m_pMeshLibrary == NULL || m_pEffectLibrary == NULL || pTexture == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	CDXMesh* pUnitRect = NULL;
	hr = m_pMeshLibrary->GetMeshByName(MESHNAME_UNITRECT, &pUnitRect);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	CDXEffect* pEffect = NULL;
	hr = m_pEffectLibrary->GetEffectByName(FXNAME_BASICRENDER, &pEffect);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	float rectW = rect.right - rect.left;
	float rectH = rect.bottom - rect.top;
	if (rectW <=0 || rectH <= 0)
	{
		assert(0);
		return E_FAIL;
	}
	UINT stretchType = (UINT)sType;
	BOOL bDrawTexture = TRUE;
	UINT sampleType = 1; 
	bool bFlipY = false;
	bool bFlipX = false;
	float rtRatio = rectW / rectH;
	hr = pEffect->SetShaderResourceVariableByName("g_Texture", pTexture);
	hr = pEffect->SetVariableByName("g_rtRatio", (void*)&rtRatio, 0, sizeof(rtRatio));
	hr = pEffect->SetVariableByName("g_bDrawTexture", (void*)&bDrawTexture, 0, sizeof(bDrawTexture));
	hr = pEffect->SetVariableByName("g_StretchType", (void*)&stretchType, 0, sizeof(stretchType) );
	hr = pEffect->SetVariableByName("g_color", color, 0, sizeof(FLOAT)*4);
	hr = pEffect->SetVariableByName("g_sampleType", (void*)&sampleType, 0, sizeof(sampleType));
	hr = pEffect->SetVariableByName("g_bFlipX", (void*)&bFlipX, 0, sizeof(bFlipX));
	hr = pEffect->SetVariableByName("g_bFlipY", (void*)&bFlipY, 0, sizeof(bFlipY));
	
	PushEffect();
	PushRenderGeometry();

	SetRenderGeometry(pUnitRect);
	SetEffect(pEffect, 0, 0);
	PushMatrix();
	TranslateLocal(rect.left, rect.top, 0.0);
	ScaleLocal(rectW, rectH, 1.0);
	DrawD3D(TRUE);
	PopMatrix();

	PopRenderGeometry();
	PopEffect();

	return S_OK;
}
HRESULT CDXRenderer::DrawRectangleD3D(D2D1_RECT_F   rect, CDXEffect* pEffect, UINT techIdx, UINT passIdx)
{
	if (m_pDevice == NULL ||  m_pMeshLibrary == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	CDXMesh* pUnitRect = NULL;
	hr = m_pMeshLibrary->GetMeshByName(MESHNAME_UNITRECT, &pUnitRect);
	if (FAILED(hr))
		return hr;
	float rectW = rect.right - rect.left;
	float rectH = rect.bottom - rect.top;
	if (rectW <=0 || rectH <= 0)
	{
		assert(0);
		return E_FAIL;
	}
	PushEffect();
	PushRenderGeometry();

	SetRenderGeometry(pUnitRect);
	SetEffect(pEffect, techIdx, passIdx);
	
	PushMatrix();
	TranslateLocal(rect.left, rect.top, 0.0);
	ScaleLocal(rectW, rectH, 1.0);
	DrawD3D(TRUE);
	PopMatrix();

	PopRenderGeometry();
	PopEffect();
	return S_OK;
}
HRESULT CDXRenderer::DrawBorderRectangleD3D(D2D1_RECT_F rect, const float bordW[4], CDXTexture2D* pTexture, FLOAT color[4])
{
	if (m_pDevice == NULL ||  m_pMeshLibrary == NULL || m_pEffectLibrary == NULL || pTexture == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();

	D3D11_TEXTURE2D_DESC desc;
	pTexture->GetDesc(&desc);

	hr = _updateBordMesh(rect, bordW, desc.Width, desc.Height);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	CDXMesh* pBorderRect = NULL;
	hr = m_pMeshLibrary->GetMeshByName(MESHNAME_BORDERRECT, &pBorderRect);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	CDXEffect* pEffect = NULL;
	hr = m_pEffectLibrary->GetEffectByName(FXNAME_BASICRENDER, &pEffect);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	float rectW = rect.right - rect.left;
	float rectH = rect.bottom - rect.top;
	if (rectW <=0 || rectH <= 0)
	{
		assert(0);
		return E_FAIL;
	}

	UINT stretchType = 0;
	BOOL bDrawTexture = TRUE;
	UINT sampleType = 1; 
	bool bFlipY = false;
	bool bFlipX = false;
	float rtRatio = rectW / rectH;
	hr = pEffect->SetShaderResourceVariableByName("g_Texture", pTexture);
	hr = pEffect->SetVariableByName("g_bDrawTexture", (void*)&bDrawTexture, 0, sizeof(bDrawTexture));
	hr = pEffect->SetVariableByName("g_rtRatio", (void*)&rtRatio, 0, sizeof(rtRatio));
	hr = pEffect->SetVariableByName("g_StretchType", (void*)&stretchType, 0, sizeof(stretchType) );
	hr = pEffect->SetVariableByName("g_color", color, 0, sizeof(FLOAT)*4);
	hr = pEffect->SetVariableByName("g_sampleType", (void*)&sampleType, 0, sizeof(sampleType));
	hr = pEffect->SetVariableByName("g_bFlipX", (void*)&bFlipX, 0, sizeof(bFlipX));
	hr = pEffect->SetVariableByName("g_bFlipY", (void*)&bFlipY, 0, sizeof(bFlipY));

	PushEffect();
	PushRenderGeometry();

	SetRenderGeometry(pBorderRect);
	SetEffect(pEffect, 0, 0);
	
	DrawD3D(TRUE);
	

	PopRenderGeometry();
	PopEffect();

	return S_OK;
	
}
HRESULT CDXRenderer::DrawBorderRectangleD3D(D2D1_RECT_F rect, const float bordW[4], UINT texW, UINT texH, CDXEffect* pEffect, UINT techIdx, UINT passIdx)
{
	if (m_pDevice == NULL ||  m_pMeshLibrary == NULL || pEffect == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();

	hr = _updateBordMesh(rect, bordW, texW, texH);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	CDXMesh* pBorderRect = NULL;
	hr = m_pMeshLibrary->GetMeshByName(MESHNAME_BORDERRECT, &pBorderRect);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	
	UINT stretchType = 0;
	BOOL bDrawTexture = TRUE;
	UINT sampleType = 0; 
	bool bFlipY = false;
	bool bFlipX = false;

	float rectW = rect.right - rect.left;
	float rectH = rect.bottom - rect.top;
	if (rectW <=0 || rectH <= 0)
	{
		assert(0);
		return E_FAIL;
	}
	PushEffect();
	PushRenderGeometry();

	SetRenderGeometry(pBorderRect);
	SetEffect(pEffect, 0, 0);
	PushMatrix();
	TranslateLocal(rect.left, rect.top, 0.0);
	ScaleLocal(rectW, rectH, 1.0);
	DrawD3D(TRUE);
	PopMatrix();

	PopRenderGeometry();
	PopEffect();

	return S_OK;
}

HRESULT CDXRenderer::CreateD2DMesh(ID2D1Mesh **mesh)
{
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	return pD2DRT->CreateMesh(mesh);
}

/////////3D Render Command///////////////
HRESULT CDXRenderer::ClearColorD3D(FLOAT color[4])
{
	if (m_pDevice == NULL || m_pFrameBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	ID3D11RenderTargetView* pRTView = NULL;
	hr = m_pFrameBuffer->GetRenderTargetView(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &pRTView);
	if (FAILED(hr))
		return hr;
	m_pFrameBuffer->KeyMutex11Acquire();
	pContext->ClearRenderTargetView(pRTView, color);
	m_pFrameBuffer->KeyMutex11Release();
	return S_OK;
}

HRESULT CDXRenderer::ClearDepthD3D()
{
	if (m_pDevice == NULL || m_pDepthBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID3D11DeviceContext* pContext = m_pDevice->GetD3D11DeviceContext();
	ID3D11DepthStencilView* pDSView = NULL;
	hr = m_pDepthBuffer->GetDepthStencilView(NULL, &pDSView);
	if (FAILED(hr))
		return hr;
	m_pDepthBuffer->KeyMutex11Acquire();
	pContext->ClearDepthStencilView(pDSView, D3D11_CLEAR_DEPTH, 1.0, 1);
	m_pDepthBuffer->KeyMutex11Acquire();
	return S_OK;
}

HRESULT CDXRenderer::BeginDrawD3D()
{
	HRESULT hr = S_OK;
	if (m_pFrameBuffer == NULL || m_bD3DDrawing)
	{
		assert(0);
		return E_FAIL;
	}
	if (m_bD2DDrawing)
	{
		hr = EndDraw();
		m_bD2DDrawingEndByD3D = TRUE;
	}
	m_bD3DDrawing = TRUE;
	return hr;
}	
HRESULT CDXRenderer::EndDrawD3D()
{
	if (m_pFrameBuffer == NULL || !m_bD3DDrawing )
	{
		assert(0);
		return E_FAIL;
	}
	HRESULT hr = S_OK;
	if (m_bD2DDrawingEndByD3D)
	{
		hr = BeginDraw();
		m_bD2DDrawingEndByD3D = FALSE;
	}
	m_bD3DDrawing = FALSE;
	return hr;
}
////////2D Render Command
HRESULT CDXRenderer::BeginDraw()
{
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	m_pFrameBuffer->KeyMutex10Acquire();
	
	pD2DRT->BeginDraw();
	m_bD2DDrawing = TRUE;
	return S_OK;

}
HRESULT CDXRenderer::EndDraw()
{
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	
	//LockDrawCmdResource10(); //now we locked in each drawing function call
	D2D1_TAG tag1;
	D2D1_TAG tag2;
	hr = pD2DRT->EndDraw(&tag1, &tag2);
	if (FAILED(hr))
	{
		assert(0);
	}
	UnLockAndClearDrawCmdResource10();
	m_pFrameBuffer->KeyMutex10Release();
	m_bD2DDrawing = FALSE;
	return hr;
}
HRESULT CDXRenderer::ClearColor(FLOAT color[4])
{
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	D2D1_COLOR_F clr = {color[0], color[1], color[2], color[3]};
	
	hr = m_pFrameBuffer->KeyMutex10Acquire();
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->Clear(clr);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	hr = m_pFrameBuffer->KeyMutex10Release();
	return S_OK;
}
HRESULT CDXRenderer::DrawBitmapSubRegion(CDXTexture2D* pTexture, D2D1_RECT_F destinationRectangle, D2D1_RECT_F   srcRect,
						   FLOAT opacity, D2D1_BITMAP_INTERPOLATION_MODE interpolationMode )
{
	if (pTexture == NULL)
		return E_INVALIDARG;
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1Bitmap* pBitmap = NULL;
	hr = pTexture->GetD2DBitmap(pD2DRT, &pBitmap);
	if (FAILED(hr))
		return hr;
	hr = _PushAndLockDrawCmdResource10(pTexture);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawBitmap(pBitmap, destinationRectangle, opacity, interpolationMode, &srcRect);
	UnbindD2DClipRect();
	UnbindD2DTransform();

	return hr;
}
HRESULT CDXRenderer::DrawBitmap(CDXTexture2D* pTexture, D2D1_RECT_F destinationRectangle, StretchType stretchType,
						   FLOAT opacity, D2D1_BITMAP_INTERPOLATION_MODE interpolationMode )
{
	if (pTexture == NULL)
		return E_INVALIDARG;
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	D2D1_RECT_F srcRect;
	D2D1_RECT_F dstRect;

	D3D11_TEXTURE2D_DESC desc;
	pTexture->GetDesc(&desc);

	_CalcStretchTypeSrcRect(stretchType, destinationRectangle, (float)desc.Width, (float)desc.Height, dstRect, srcRect);
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1Bitmap* pBitmap = NULL;
	hr = pTexture->GetD2DBitmap(pD2DRT, &pBitmap);
	if (FAILED(hr))
		return hr;
	hr = _PushAndLockDrawCmdResource10(pTexture);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawBitmap(pBitmap, dstRect, opacity, interpolationMode, srcRect);
	UnbindD2DClipRect();
	UnbindD2DTransform();

	return hr;
}
HRESULT CDXRenderer::DrawBitmapEx(ID2D1Bitmap* pBitmap, D2D1_RECT_F destinationRectangle, 
						   FLOAT opacity, D2D1_BITMAP_INTERPOLATION_MODE interpolationMode, const D2D1_RECT_F* sourceRectangle )
{
	if (pBitmap == NULL)
		return E_INVALIDARG;
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	D2D1_RECT_F srcRect;
	if (sourceRectangle == NULL)
	{
		D2D_SIZE_F sz = pBitmap->GetSize();
		srcRect.left = 0;
		srcRect.top = 0;
		srcRect.right = sz.width;
		srcRect.bottom = sz.height;
	}
	else
	{
		srcRect = *sourceRectangle;
	}
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawBitmap(pBitmap, destinationRectangle, opacity, interpolationMode, srcRect);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}

HRESULT CDXRenderer::DrawBorderBitmap(CDXTexture2D* pTexture, const float bordW[4], D2D1_RECT_F dstRect,
								 FLOAT opacity, D2D1_BITMAP_INTERPOLATION_MODE interpolationMode, const D2D1_RECT_F* sourceRectangle)
{
	if (pTexture == NULL)
		return E_INVALIDARG;
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	D3D11_TEXTURE2D_DESC desc;
	pTexture->GetDesc(&desc);

	D2D1_RECT_F srcRect;
	if (sourceRectangle == NULL)
	{	
		srcRect.left = 0;
		srcRect.top = 0;
		srcRect.right = (float)desc.Width;
		srcRect.bottom = (float)desc.Height;
	}
	else
	{
		srcRect = *sourceRectangle;
	}
	
	D2D_RECT_F _srcRect[9];
	D2D_RECT_F _dstRect[9];

	//4 cornder
	_srcRect[0] = D2D1::RectF(srcRect.left,              srcRect.top,               srcRect.left + bordW[0],         srcRect.top + bordW[1]); // LT
	_srcRect[1] = D2D1::RectF(srcRect.right - bordW[2],  srcRect.top,               srcRect.right,                   srcRect.top + bordW[1]); // RT
	_srcRect[2] = D2D1::RectF(srcRect.left,        srcRect.bottom - bordW[3],       srcRect.left + bordW[0],         srcRect.bottom); // LB
	_srcRect[3] = D2D1::RectF(srcRect.right - bordW[2],  srcRect.bottom - bordW[3], srcRect.right,                   srcRect.bottom); // RB
	//4 edge
	_srcRect[4] = D2D1::RectF(srcRect.left+bordW[0],     srcRect.top,                srcRect.right - bordW[2],       srcRect.top + bordW[1]); // Top
	_srcRect[5] = D2D1::RectF(srcRect.left+bordW[0], srcRect.bottom - bordW[3],      srcRect.right - bordW[2],       srcRect.bottom); // Bottom
	_srcRect[6] = D2D1::RectF(srcRect.left,          srcRect.top + bordW[1],         srcRect.left + bordW[0],        srcRect.bottom - bordW[3]); // Left
	_srcRect[7] = D2D1::RectF(srcRect.right - bordW[2], srcRect.top + bordW[1],      srcRect.right ,                 srcRect.bottom - bordW[3]); // right
	//center
	_srcRect[8] = D2D1::RectF(srcRect.left + bordW[0], srcRect.top + bordW[1],      srcRect.right - bordW[2],       srcRect.bottom - bordW[3]); // right

	//4 cornder
	_dstRect[0] = D2D1::RectF(dstRect.left,              dstRect.top,               dstRect.left + bordW[0],         dstRect.top + bordW[1]); // LT
	_dstRect[1] = D2D1::RectF(dstRect.right - bordW[2],  dstRect.top,               dstRect.right,                   dstRect.top + bordW[1]); // RT
	_dstRect[2] = D2D1::RectF(dstRect.left,        dstRect.bottom - bordW[3],       dstRect.left + bordW[0],         dstRect.bottom); // LB
	_dstRect[3] = D2D1::RectF(dstRect.right - bordW[2],  dstRect.bottom - bordW[3], dstRect.right,                   dstRect.bottom); // RB
	//4 edge
	_dstRect[4] = D2D1::RectF(dstRect.left+bordW[0],     dstRect.top,                dstRect.right - bordW[2],       dstRect.top + bordW[1]); // Top
	_dstRect[5] = D2D1::RectF(dstRect.left+bordW[0], dstRect.bottom - bordW[3],      dstRect.right - bordW[2],       dstRect.bottom); // Bottom
	_dstRect[6] = D2D1::RectF(dstRect.left,          dstRect.top + bordW[1],         dstRect.left + bordW[0],        dstRect.bottom - bordW[3]); // Left
	_dstRect[7] = D2D1::RectF(dstRect.right - bordW[2], dstRect.top + bordW[1],      dstRect.right,                  dstRect.bottom - bordW[3]); // right
	//center
	_dstRect[8] = D2D1::RectF(dstRect.left + bordW[0], dstRect.top + bordW[1],      dstRect.right - bordW[2],       dstRect.bottom - bordW[3]); // right

	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1Bitmap* pBitmap = NULL;
	hr = pTexture->GetD2DBitmap(pD2DRT, &pBitmap);
	if (FAILED(hr))
		return hr;
	hr = _PushAndLockDrawCmdResource10(pTexture);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	BindD2DTransform();
	BindD2DClipRect();
	for (UINT i =0; i < 9; i++)
	{
		pD2DRT->DrawBitmap(pBitmap, _dstRect[i], opacity, interpolationMode, _srcRect[i]);
	}
	
	UnbindD2DClipRect();
	UnbindD2DTransform();
	

	return S_OK;
}
HRESULT CDXRenderer::DrawEllipse( const D2D1_ELLIPSE &ellipse, ID2D1Brush* brush, FLOAT strokeWidth)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawEllipse(ellipse, brush, strokeWidth);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawTexturedEllipse( const D2D1_ELLIPSE &ellipse, CDXTexture2D* brush, FLOAT strokeWidth)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1BitmapBrush* pBrush = NULL;
	hr = brush->GetD2DBitmapBrush(pD2DRT, &pBrush);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawEllipse(ellipse, pBrush, strokeWidth);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawColorEllipse( const D2D1_ELLIPSE &ellipse, FLOAT color[4], FLOAT strokeWidth)
{
	if (m_pFrameBuffer == NULL || m_pColorBrushLibrary == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;

	ID2D1SolidColorBrush* pBrush = NULL;
	D2D1_COLOR_F clr = {color[0], color[1], color[2], color[3]};
	hr = m_pColorBrushLibrary->GetSolidColorBrush(pD2DRT, clr, &pBrush );
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawEllipse(ellipse, pBrush, strokeWidth);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawGeometry( ID2D1Geometry *geometry, ID2D1Brush *brush, FLOAT strokeWidth, ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || brush == NULL || geometry == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawGeometry(geometry, brush, strokeWidth);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawColorGeometry( ID2D1Geometry *geometry, FLOAT color[4], FLOAT strokeWidth, ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || m_pColorBrushLibrary == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;

	ID2D1SolidColorBrush* pBrush = NULL;
	D2D1_COLOR_F clr = {color[0], color[1], color[2], color[3]};
	hr = m_pColorBrushLibrary->GetSolidColorBrush(pD2DRT, clr, &pBrush );
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawGeometry(geometry, pBrush, strokeWidth);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawTexturedGeometry( ID2D1Geometry *geometry, CDXTexture2D* pBrush, FLOAT strokeWidth, ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || pBrush == NULL || geometry == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1BitmapBrush* brush = NULL;
	hr = pBrush->GetD2DBitmapBrush(pD2DRT, &brush);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawGeometry(geometry, brush, strokeWidth);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}

HRESULT CDXRenderer::DrawLine(D2D1_POINT_2F point0, D2D1_POINT_2F point1, ID2D1Brush *brush, FLOAT strokeWidth,
						 ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawLine(point0, point1, brush, strokeWidth, strokeStyle);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawTexturedLine(D2D1_POINT_2F point0, D2D1_POINT_2F point1, CDXTexture2D *brush, FLOAT strokeWidth,
						 ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1BitmapBrush* pBrush = NULL;
	hr = brush->GetD2DBitmapBrush(pD2DRT, &pBrush);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawLine(point0, point1, pBrush, strokeWidth, strokeStyle);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawColorLine(D2D1_POINT_2F point0, D2D1_POINT_2F point1, FLOAT color[4], FLOAT strokeWidth,
						 ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || m_pColorBrushLibrary == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;

	ID2D1SolidColorBrush* pBrush = NULL;
	D2D1_COLOR_F clr = {color[0], color[1], color[2], color[3]};
	hr = m_pColorBrushLibrary->GetSolidColorBrush(pD2DRT, clr, &pBrush );
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawLine(point0, point1, pBrush, strokeWidth, strokeStyle);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawRectangle(D2D1_RECT_F rect, ID2D1Brush *brush, FLOAT strokeWidth, ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawRectangle(rect, brush, strokeWidth, strokeStyle);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawTexturedRectangle(D2D1_RECT_F rect, CDXTexture2D* brush, FLOAT strokeWidth, ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1BitmapBrush* pBrush = NULL;
	hr = brush->GetD2DBitmapBrush(pD2DRT, &pBrush);
	if (FAILED(hr))
		return hr;
	hr = _PushAndLockDrawCmdResource10(brush);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawRectangle(&rect, pBrush, strokeWidth, strokeStyle);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	
	
	return S_OK;
}
HRESULT CDXRenderer::DrawColorRectangle(D2D1_RECT_F rect, FLOAT color[4], FLOAT strokeWidth, ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || m_pColorBrushLibrary == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;

	ID2D1SolidColorBrush* pBrush = NULL;
	D2D1_COLOR_F clr = {color[0], color[1], color[2], color[3]};
	hr = m_pColorBrushLibrary->GetSolidColorBrush(pD2DRT, clr, &pBrush );
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawRectangle(rect, pBrush, strokeWidth, strokeStyle);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawRoundedRectangle(const D2D1_ROUNDED_RECT &roundedRect, ID2D1Brush *brush, FLOAT strokeWidth, ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawRoundedRectangle(roundedRect, brush, strokeWidth, strokeStyle);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawTexturedRoundedRectangle(const D2D1_ROUNDED_RECT &roundedRect, CDXTexture2D *pBrush, FLOAT strokeWidth, ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || pBrush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1BitmapBrush* brush = NULL;
	hr = pBrush->GetD2DBitmapBrush(pD2DRT, &brush);
	if (FAILED(hr))
		return hr;
	hr = _PushAndLockDrawCmdResource10(pBrush);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawRoundedRectangle(roundedRect, brush, strokeWidth, strokeStyle);
	UnbindD2DClipRect();
	UnbindD2DTransform();

	return S_OK;
}
HRESULT CDXRenderer::DrawColorRoundedRectangle(const D2D1_ROUNDED_RECT &roundedRect, FLOAT color[4], FLOAT strokeWidth, ID2D1StrokeStyle *strokeStyle)
{
	if (m_pFrameBuffer == NULL || m_pColorBrushLibrary == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;

	ID2D1SolidColorBrush* pBrush = NULL;
	D2D1_COLOR_F clr = {color[0], color[1], color[2], color[3]};
	hr = m_pColorBrushLibrary->GetSolidColorBrush(pD2DRT, clr, &pBrush );
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawRoundedRectangle(roundedRect, pBrush, strokeWidth, strokeStyle);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawText(WCHAR *txtString, UINT stringLength,  IDWriteTextFormat *textFormat, D2D1_RECT_F layoutRect,
						 ID2D1Brush *defaultForegroundBrush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuringMode)
{
	if (m_pFrameBuffer == NULL || defaultForegroundBrush == NULL || txtString == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawText(txtString, stringLength, textFormat, layoutRect, defaultForegroundBrush, options, measuringMode);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawColorText(WCHAR *txtString, UINT stringLength,  IDWriteTextFormat *textFormat, D2D1_RECT_F layoutRect,
						 FLOAT color[4], D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuringMode)
{
	if (m_pFrameBuffer == NULL || m_pColorBrushLibrary == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;

	ID2D1SolidColorBrush* pBrush = NULL;
	D2D1_COLOR_F clr = {color[0], color[1], color[2], color[3]};
	hr = m_pColorBrushLibrary->GetSolidColorBrush(pD2DRT, clr, &pBrush );
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawText(txtString, stringLength, textFormat, layoutRect, pBrush, options, measuringMode);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawTexturedText(WCHAR *txtString, UINT stringLength,  IDWriteTextFormat *textFormat, D2D1_RECT_F layoutRect,
						 CDXTexture2D *pBrush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuringMode)
{
	if (m_pFrameBuffer == NULL || pBrush == NULL || txtString == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1BitmapBrush* brush = NULL;
	hr = pBrush->GetD2DBitmapBrush(pD2DRT, &brush);
	if (FAILED(hr))
		return hr;
	hr = _PushAndLockDrawCmdResource10(pBrush);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawText(txtString, stringLength, textFormat, layoutRect, brush, options, measuringMode);
	UnbindD2DClipRect();
	UnbindD2DTransform();

	return S_OK;
}

HRESULT CDXRenderer::DrawTextLayout(D2D1_POINT_2F origin, IDWriteTextLayout *textLayout, ID2D1Brush *defaultForegroundBrush, D2D1_DRAW_TEXT_OPTIONS options)
{
	if (m_pFrameBuffer == NULL || defaultForegroundBrush == NULL )
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawTextLayout(origin, textLayout, defaultForegroundBrush, options);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawColorTextLayout(D2D1_POINT_2F origin, IDWriteTextLayout *textLayout, FLOAT color[4], D2D1_DRAW_TEXT_OPTIONS options)
{
	if (m_pFrameBuffer == NULL || m_pColorBrushLibrary == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;

	ID2D1SolidColorBrush* pBrush = NULL;
	D2D1_COLOR_F clr = {color[0], color[1], color[2], color[3]};
	hr = m_pColorBrushLibrary->GetSolidColorBrush(pD2DRT, clr, &pBrush );
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawTextLayout(origin, textLayout, pBrush, options);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::DrawTexturedTextLayout(D2D1_POINT_2F origin, IDWriteTextLayout *textLayout, CDXTexture2D* pBrush, D2D1_DRAW_TEXT_OPTIONS options)
{
	if (m_pFrameBuffer == NULL || pBrush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1BitmapBrush* brush = NULL;
	hr = pBrush->GetD2DBitmapBrush(pD2DRT, &brush);
	if (FAILED(hr))
		return hr;
	hr = _PushAndLockDrawCmdResource10(pBrush);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawTextLayout(origin, textLayout, brush, options);
	UnbindD2DClipRect();
	UnbindD2DTransform();

	return S_OK;
}
HRESULT CDXRenderer::FillEllipse(const D2D1_ELLIPSE &ellipse, ID2D1Brush *brush)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->DrawEllipse(ellipse, brush);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::FillTexturedEllipse(const D2D1_ELLIPSE &ellipse, CDXTexture2D *brush)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1BitmapBrush* pBrush = NULL;
	hr = brush->GetD2DBitmapBrush(pD2DRT, &pBrush);
	if (FAILED(hr))
		return hr;
	hr = _PushAndLockDrawCmdResource10(brush);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->FillEllipse(ellipse, pBrush);
	UnbindD2DClipRect();
	UnbindD2DTransform();

	return S_OK;
}
HRESULT CDXRenderer::FillColorEllipse(const D2D1_ELLIPSE &ellipse, FLOAT color[4])
{
	if (m_pFrameBuffer == NULL || m_pColorBrushLibrary == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;

	ID2D1SolidColorBrush* pBrush = NULL;
	D2D1_COLOR_F clr = {color[0], color[1], color[2], color[3]};
	hr = m_pColorBrushLibrary->GetSolidColorBrush(pD2DRT, clr, &pBrush );
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->FillEllipse(ellipse,  pBrush);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::FillGeometry(ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacityBrush)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->FillGeometry(geometry, brush, opacityBrush);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::FillOpacityMask( ID2D1Bitmap *opacityMask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
								D2D1_RECT_F destinationRectangle, D2D1_RECT_F sourceRectangle)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->FillOpacityMask(opacityMask, brush, content, destinationRectangle, sourceRectangle);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::FillTexturedOpacityMask( CDXTexture2D *opacityMask, CDXTexture2D *brush, D2D1_OPACITY_MASK_CONTENT content,
								D2D1_RECT_F destinationRectangle, D2D1_RECT_F sourceRectangle)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1Bitmap* pbitmap = NULL;
	hr = opacityMask->GetD2DBitmap(pD2DRT, &pbitmap);
	if (FAILED(hr))
		return hr;
	ID2D1BitmapBrush* pbitmapBrush = NULL;
	hr = opacityMask->GetD2DBitmapBrush(pD2DRT, &pbitmapBrush);
	if (FAILED(hr))
		return hr;
	hr = _PushAndLockDrawCmdResource10(brush);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->FillOpacityMask(pbitmap, pbitmapBrush, content, destinationRectangle, sourceRectangle);
	UnbindD2DClipRect();
	UnbindD2DTransform();

	return S_OK;
}

HRESULT CDXRenderer::FillRectangle( D2D1_RECT_F rect, ID2D1Brush *brush)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->FillRectangle(rect, brush);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::FillColorRectangle( D2D1_RECT_F rect, float color[4])
{
	if (m_pFrameBuffer == NULL || m_pColorBrushLibrary == NULL)
		return E_FAIL;

	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;

	ID2D1SolidColorBrush* pBrush = NULL;
	D2D1_COLOR_F clr = {color[0], color[1], color[2], color[3]};
	hr = m_pColorBrushLibrary->GetSolidColorBrush(pD2DRT, clr, &pBrush );
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->FillRectangle(rect, pBrush);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::FillTexturedRectangle( D2D1_RECT_F rect, CDXTexture2D* brush)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1BitmapBrush* pBitmapBrush = NULL;
	hr = brush->GetD2DBitmapBrush(pD2DRT, &pBitmapBrush);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	hr = _PushAndLockDrawCmdResource10(brush);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->FillRectangle(&rect, pBitmapBrush);
	UnbindD2DClipRect();
	UnbindD2DTransform();

	return S_OK;
}

HRESULT CDXRenderer::FillRoundedRectangle(const D2D1_ROUNDED_RECT &roundedRect, ID2D1Brush *brush)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->FillRoundedRectangle(roundedRect, brush);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}
HRESULT CDXRenderer::FillTexturedRoundedRectangle(const D2D1_ROUNDED_RECT &roundedRect, CDXTexture2D *brush)
{
	if (m_pFrameBuffer == NULL || brush == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	ID2D1BitmapBrush* pBrush = NULL;
	hr = brush->GetD2DBitmapBrush(pD2DRT, &pBrush);
	if (FAILED(hr))
		return hr;
	hr = _PushAndLockDrawCmdResource10(brush);
	if (FAILED(hr))
	{
		assert(0);
		return hr;
	}
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->FillRoundedRectangle(roundedRect, pBrush);
	UnbindD2DClipRect();
	UnbindD2DTransform();

	return S_OK;
}
HRESULT CDXRenderer::FillColorRoundedRectangle(const D2D1_ROUNDED_RECT &roundedRect, FLOAT color[4])
{
	if (m_pFrameBuffer == NULL || m_pColorBrushLibrary == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;

	ID2D1SolidColorBrush* pBrush = NULL;
	D2D1_COLOR_F clr = {color[0], color[1], color[2], color[3]};
	hr = m_pColorBrushLibrary->GetSolidColorBrush(pD2DRT, clr, &pBrush );
	if (FAILED(hr))
		return hr;
	BindD2DTransform();
	BindD2DClipRect();
	pD2DRT->FillRoundedRectangle(roundedRect, pBrush);
	UnbindD2DClipRect();
	UnbindD2DTransform();
	return S_OK;
}

///2D State Setting
HRESULT CDXRenderer::SaveDrawingState(ID2D1DrawingStateBlock *drawingStateBlock)
{
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	pD2DRT->SaveDrawingState(drawingStateBlock);
	return S_OK;
}
HRESULT CDXRenderer::RestoreDrawingState(ID2D1DrawingStateBlock *drawingStateBlock)
{
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	pD2DRT->RestoreDrawingState(drawingStateBlock);
	return S_OK;
}
HRESULT CDXRenderer::PushAxisAlignedClip(D2D1_RECT_F clipRect, D2D1_ANTIALIAS_MODE antialiasMode)
{
	m_clipRectStack.push_back(m_pClipRect);
	
	D3DXVECTOR3 lt(clipRect.left, clipRect.top, 0);
	D3DXVECTOR3 rt(clipRect.right, clipRect.top, 0);
	D3DXVECTOR3 lb(clipRect.left, clipRect.bottom, 0);
	D3DXVECTOR3 rb(clipRect.right, clipRect.bottom, 0);
	
	D3DXVECTOR3 orgPt[] = {lt, rt, lb, rb};
	D3DXVECTOR3 globalPt[4];
	Transform3DPoints(globalPt, orgPt, 4);

	m_pClipRect = new ClipRectSet(globalPt, antialiasMode);
	return S_OK;
}
HRESULT CDXRenderer::PopAxisAlignedClip()
{
	if (m_clipRectStack.empty())
	{
		assert(0);
		return E_FAIL;
	}
	SAFE_DELETE(m_pClipRect);
	m_pClipRect = m_clipRectStack.back();
	m_clipRectStack.pop_back();
	return S_OK;
}
HRESULT CDXRenderer::SetAntialiasMode(D2D1_ANTIALIAS_MODE antialiasMode)
{
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	pD2DRT->SetAntialiasMode(antialiasMode);
	return S_OK;
}
HRESULT CDXRenderer::GetAntialiasMode(D2D1_ANTIALIAS_MODE* pAntialiasMode)
{
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;

	*pAntialiasMode = pD2DRT->GetAntialiasMode();
	return S_OK;
}
HRESULT CDXRenderer::SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE textAntialiasMode)
{
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	pD2DRT->SetTextAntialiasMode(textAntialiasMode);
	return S_OK;
}
HRESULT CDXRenderer::GetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE* textAntialiasMode)
{
	if (m_pFrameBuffer == NULL)
		return E_FAIL;
	HRESULT hr = S_OK;
	ID2D1RenderTarget* pD2DRT = NULL;
	hr = m_pFrameBuffer->GetD2DRenderTarget(&pD2DRT);
	if (FAILED(hr))
		return hr;
	*textAntialiasMode = pD2DRT->GetTextAntialiasMode();
	return S_OK;
}